package Olivia.manager
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.utils.Dictionary;
	
	public class ResManager extends EventDispatcher
	{
		//open pipe or parellel
		private static var _pipeLining:Boolean = true;
		
		//thread count
		private static var _lines:int = 5;
		
		//loaders
		private static var _loaderList:Array;
		//loading urls
		private static var _loadingUrlList:Array;
		//loading thred count
		private static var _loadingLines:int;
		
		//waiting List
		private static var _waitList:Array;
		//store List
		private static var _storeList:Dictionary = new Dictionary();
		
		public function ResManager()
		{
			
		}
		
		public static function load(url:String, callBack:Function=null, param:*=null):void
		{
			//_storeList contain(url)
			var res:* = getResource(url);
			if(res == null)
			{
				//go load
				goLoad(url, callBack, param);
			}
			else
			{
				//call back
				if(callBack != null)
				{
					if(param == null)
					{
						callBack.call(null, res);
					}
					else
					{
						callBack.call(null, res, param);
					}
				}
				popWaitingRes();
			}
		}
		
		private static function goLoad(url:String, callBack:Function=null, param:*=null):void
		{
			if(_loaderList == null)
			{
				_loaderList = new Array();
				_loadingUrlList = new Array();
				_loadingLines = 0;
				_waitList = new Array();
			}
			
			//loading this url;
			if(isLoading(url))
			{
				_waitList.push([url,callBack,param]);
			}
			
			var lens:int = _loaderList.length;
			if(lens < _lines)
			{
				var tempRL:ResLoader = new ResLoader();
				_loaderList.push(tempRL);
				_loadingUrlList.push(url);
				
				if(!_pipeLining)
					_loadingLines++;
				
				tempRL.addEventListener(Event.COMPLETE, completeLoader);
				tempRL.load(url,callBack,param);
			}
			else
			{
				var freeLoader:ResLoader = findFreeLoader();
				if(freeLoader != null)
				{
					_loadingUrlList.push(url);
					
					if(!_pipeLining)
						_loadingLines++;
					
					freeLoader.load(url, callBack, param);
				}
				else
				{
					_waitList.push([url, callBack, param]);
				}
			}
		}
		
		private static function findFreeLoader():ResLoader
		{
			var resLoader:ResLoader;
			var lens:int = _loaderList.length;
			for(var i:int=0; i<lens; ++i)
			{
				var tempLR:ResLoader = _loaderList[i] as ResLoader;
				if(!tempLR.loading)
				{
					resLoader = tempLR;
					break;
				}
			}
			return resLoader;
		}
		
		private static function completeLoader(e:Event):void
		{
			var freeLoader:ResLoader = e.target as ResLoader;
			if(_pipeLining)
			{
				removeLoadingUrl(freeLoader.URL);
				
				popWaitingRes();
			}
			else
			{
				_loadingLines--;
				if(_loadingLines == 0)
					clearLoadingUrl();
			}
		}
		
		private static function clearLoadingUrl():void
		{
			_loadingUrlList = new Array();
			
			var lens:int = _waitList.lenth;
			if(lens>5)
				lens = 5;
			
			for(var i:int=0; i<lens; ++i)
			{
				popWaitingRes();
			}
		}
		
		private static function popWaitingRes():void
		{
			if(_waitList.length == 0)
				return;
			
			var popArr:Array = _waitList.pop();
			load(popArr[0], popArr[1], popArr[2]);
		}
		
		private static function removeLoadingUrl(url:String):void
		{
			var lens:int = _loadingUrlList.length;
			for(var i:int=lens-1; i>-1; --i)
			{
				var tempUrl:String = _loadingUrlList[i];
				if(tempUrl == url)
				{
					_loadingUrlList.splice(i,1);
					break;
				}
			}
		}
		
		private static function isLoading(url:String):Boolean
		{
			var loading:Boolean = false;
			var lens:int = _loaderList.length;
			for(var i:int=0; i<lens; ++i)
			{
				var tempUrl:String = _loadingUrlList[i];
				if(tempUrl == url)
				{
					loading = true;
					break;
				}
			}
			return loading;
		}
			
		
		public static function getResource(url:String):*
		{
			if(_storeList[url] != null)
			{
				var returnRes:*;
				if(getResType(url) == 0)
				{
					returnRes = new Bitmap(_storeList[url] as BitmapData);
				}
				else if(getResType(url) == 1)
				{
					returnRes = new (_storeList[url] as Class);
				}
				
				return returnRes;
			}
			else
			{
				return null;
			}
		}
		
		/**
		 * 0 bitmap, 1 movieclip
		 * @param url
		 * @return resource type
		 * 
		 */		
		private static function getResType(url:String):int
		{
			var arr:Array = url.split(".");
			if(arr[arr.length - 1] != "swf")
				return 0;
			else
				return 1;
		}
		
		public static function get StoreList():Dictionary
		{
			return _storeList;
		}
	}
}